using System;
using System.Collections.Generic;
using System.Linq;

namespace Universe.OneC.DomainModel
{
    public class MetaClass
    {
        private MetaClass _Owner;
        public MetaClass BaseClass;
        public List<MetaClass> Dependents = new List<MetaClass>();
        public int Discriminator;
        public PersistentType Kind;
        public readonly MetaModel Model;
        public string Name;
        public Namespace Namespace;
        public List<MetaProperty> Properties = new List<MetaProperty>();
        public string Table;
        public System.Type Type;
        public List<MetaEnumValue> EnumValues;
        public string Synonym;

        public MetaClass(MetaModel model, string name)
        {
            this.Model = model;
            this.Name = name;
        }

        public MetaClass Root
        {
            get
            {
                MetaClass root = this;
                while (root.BaseClass != null)
                    root = root.BaseClass;

                return root;

            }
        }
        
        public List<MetaProperty> GetProperties()
        {
            List<MetaProperty> list = new List<MetaProperty>();
            for (MetaClass class2 = this; class2 != null; class2 = class2.BaseClass)
            {
                foreach (MetaProperty property in class2.Properties)
                {
                    list.Add(property);
                }
            }
            return list;
        }

        public string FullName
        {
            get
            {
                string str = "";
                for (Namespace namespace2 = this.Namespace; namespace2 != null; namespace2 = namespace2.Parent)
                {
                    str = namespace2.Name + "." + str;
                }
                string str2 = "";
                for (MetaClass class2 = this.Owner; class2 != null; class2 = class2.Owner)
                {
                    str2 = class2.Name + "." + str2;
                }
                return (str + str2 + this.Name);
            }
        }

        public MetaProperty this[string name]
        {
            get
            {
                return this.Properties.Where<MetaProperty>(delegate (MetaProperty p) {
                                                                                         return (p.Name == name);
                }).Single<MetaProperty>();
            }
        }

        public MetaClass Owner
        {
            get
            {
                return this._Owner;
            }
            set
            {
                if (value != null)
                {
                    if (this._Owner == null)
                    {
                        this._Owner = value;
                    }
                    if (this._Owner.Dependents == null)
                    {
                        this._Owner.Dependents = new List<MetaClass>();
                    }
                    if (!this._Owner.Dependents.Contains(this))
                    {
                        this._Owner.Dependents.Add(this);
                    }
                }
                else
                {
                    if (((this._Owner != null) && (this._Owner.Dependents != null)) && this._Owner.Dependents.Contains(this))
                    {
                        this._Owner.Dependents.Remove(this);
                    }
                    this._Owner = value;
                }
            }
        }

        
        public string GetGroupTitle()
        {
            List<string> nsl = new List<string>();
            Namespace ns = this.Namespace;
            while (ns != null)
            {
                nsl.Add(ns.Name);
                ns = ns.Parent;
            }

            nsl.Reverse();
            if (nsl.Count > 1)
                return nsl[1];

            else 
                return null;
        }

        public MetaClassGroup GetGroup2()
        {
            if (
                this.Name == "TablePart"
                || Name == "DocumentBase"
                || Name == "CatalogBase"
                || Name == "CharacteristicBase"
                || Name == "EnumBase"
                || Name == "AccRegBase"
                )
                return MetaClassGroup.System;

            if (this.Root.Name == "TablePart")
                return MetaClassGroup.TablePart;

            
            string title = GetGroupTitle();
            int i = 0;
            foreach (var ns in this.Model.Namespaces[0].Children)
            {
                if (ns.Name == title)
                {
                    return (MetaClassGroup) i;
                }

                i++;
            }

            return (MetaClassGroup) (-1);
        }
        
        public MetaClassGroup GetGroup()
        {
            
            List<string> bases = new List<string>();
            MetaClass mc = this.BaseClass;
            while(mc != null)
            {
                bases.Add(mc.Name);
                mc = mc.BaseClass;
            }

            bases.Reverse();

            if (bases.Count == 0)
                return MetaClassGroup.System;

            if (bases[0] == "TablePart")
                return MetaClassGroup.TablePart;

            if (bases[0] == "DocumentBase")
                return MetaClassGroup.Document;

            if (bases[0] == "CatalogBase")
            {
                if (bases.Count >= 2 && bases[1] == "CharacteristicBase")
                    return MetaClassGroup.Characteristic;
                else
                    return MetaClassGroup.Catalog;
            }

            if (bases[0] == "EnumBase")
                return MetaClassGroup.Enum;

            if (bases[0] == "AccRegBase") 
                return MetaClassGroup.AccumulationRegister;

            return MetaClassGroup.System;
        }
    }
}